/*BOXD为接线盒数字型，由宫老师开发。
BOXD和DT45数字型之间通过RS485相连，协议为modbus-rtu，BOXD为主机，提供各种寄存器。
RS485为DT45D的USART3。
*/
#include <stdio.h>
#include <string.h>

#include "stm32l4xx.h"
#include "stm32l4xx_ll_bus.h"
#include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx_ll_gpio.h"
#include "stm32l4xx_ll_lpuart.h"
#include "stm32l4xx_ll_usart.h"

#include "bsp_uart_ble.h"		//没什么用处。
#include "bsp_modbus.h"
#include "bsp.h"




#define MODE_7_E_1								0
#define MODE_7_O_1								1
#define MODE_8_E_1								2
#define MODE_8_O_1								3
#define MODE_8_n_1								4
#define MODE_8_n_2								5


const uint32_t tbl_baud_ble[]={/*1200,4800,*/9600,19200,38400,57600,115200, 0};
const char* tbl_fmt_ble[]={/*" 7-E-1", " 7-O-1",*/  " 8-n-2", " 8-O-1", " 8-E-1", " 8-n-1", ""};


UART_CFG2 uart_to_ble_cfg={9600, MODE_8_E_1, 0};


/*设置RS485的串口模式，波特率和当前状态。
*/
void bsp_uart_ble_config(const char* fmt, uint32_t baud, uint8_t sta)
{
	uint32_t pclk1_clock;
	uint32_t baud_rate;
	
	
	baud_rate= baud;
//	switch (baud)
//	{	case 0:
//			baud_rate= 9600;
//			break;
//		
//		case 1:
//			baud_rate= 19200;
//			break;
//		
//		case 2:
//			baud_rate= 38400;
//			break;
//		
//		case 3:
//			baud_rate= 57600;
//			break;
//		
//		case 4:
//			baud_rate= 115200;
//			break;
//		
//		default:
//			baud_rate= 9600;
//	}		

	
	if(baud_rate< 19200){	
		//使能HSI，并等待稳定。
		LL_RCC_HSI_Enable();
		while(0 == LL_RCC_HSI_IsReady()){}	//不能使用LL_RCC_IsActiveFlag_HSIRDY()。
			
		LL_RCC_SetUSARTClockSource(LL_RCC_USART2_CLKSOURCE_HSI);
		pclk1_clock= 16000000;	//没找到更合适的函数，暂直接指定值。
	}
	else{
		LL_RCC_SetUSARTClockSource(LL_RCC_USART2_CLKSOURCE_SYSCLK);
		pclk1_clock= 48000000;
	}
	
	pclk1_clock= LL_RCC_GetUSARTClockFreq(LL_RCC_USART2_CLKSOURCE);
	LL_USART_SetBaudRate(UART_BLE, pclk1_clock, 0, baud_rate);	//第3个参数是OverSampling。 QQ可以在USART使能时，更改波特率吗？

	
	if(0 != uart_to_ble_cfg.sta){
		//先将USART3关闭。
		LL_USART_Disable(UART_BLE);
	}
	
	
//	switch (mode)
//	{	
//		case MODE_8_E_1:
//			LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_9B, LL_USART_PARITY_EVEN, LL_USART_STOPBITS_1);	//奇偶校验时，数据宽度须为9B。
//			break;
//		
//		case MODE_8_O_1:
//			LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_9B, LL_USART_PARITY_ODD, LL_USART_STOPBITS_1);
//			break;
//		
//		case MODE_8_n_1:
//			LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
//			break;
//		
//		case MODE_8_n_2:
//			LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_2);
//			break;
//		
//		default:
//			LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_9B, LL_USART_PARITY_EVEN, LL_USART_STOPBITS_1);
//	}
	if(0){
	}
	else if(0 == strcmp(fmt, FMT_8_E_1)){
		LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_9B, LL_USART_PARITY_EVEN, LL_USART_STOPBITS_1);	//奇偶校验时，数据宽度须为9B。
	}
	else if(0 == strcmp(fmt, FMT_8_O_1)){
		LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_9B, LL_USART_PARITY_EVEN, LL_USART_STOPBITS_1);	//奇偶校验时，数据宽度须为9B。
	}
	else if(0 == strcmp(fmt, FMT_8_n_1)){
		LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
	}
	else if(0 == strcmp(fmt, FMT_8_n_2)){
		LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_2);
	}
	else{	//FMT_8_L_1...
		LL_USART_ConfigCharacter(UART_BLE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
	}
	
	
	if(0 == sta){
		//先将USART3关闭。
		LL_USART_Enable(UART_BLE);
	}
	
	//RS485_BOXD_RX;
	
	//根据波特率，设定接收超时时间（暂统一）
	modbus_recv_info_ble.tmo_max= 100;	//500ms
}


//
///*设置RS485的串口的波特率。
//*/
//void bsp_uart_ble_config_baud(uint16_t baud)
//{
//	bsp_uart_boxd_config(uart_to_ble_cfg.fmt, baud, 0);
//	uart_to_ble_cfg.baud= baud;
//}


///*设置RS485的串口的数据格式。
//*/
//void bsp_uart_ble_config_format(char* fmt)
//{
//	bsp_uart_boxd_config(fmt, uart_to_ble_cfg.baud, 0);
//	strcpy(uart_to_ble_cfg.fmt, fmt);		//uart_to_ble_cfg.fmt= fmt;
//}


static void bsp_uart_ble_hal(void)
{
	LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);

	/*
	TX		Pin16/PA2	USART2。
	RX		Pin17/PA3	USART2。
	*/
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_2, LL_GPIO_MODE_ALTERNATE);
	LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_2, LL_GPIO_AF_7);				//C AF7 as USART2_TX.
	
	LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_3, LL_GPIO_PULL_UP);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_3, LL_GPIO_MODE_ALTERNATE);
	LL_GPIO_SetAFPin_0_7(GPIOA, LL_GPIO_PIN_3, LL_GPIO_AF_7);				//C AF7 as USART2_RX.
}



/*配置MCU和BOXD盒相连的串口。
!!需要开启相应时钟。
!!115200用11520标示。
*/
void bsp_uart_ble_init(uint32_t baud, const char* fmt)
{
	bsp_uart_ble_hal();
	
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2);
	//LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_SYSCLK);		//PCLK as USART1's clock source,!!Must enable USART1_EN@RCC_APB1ENR1.
	
	LL_USART_Disable(UART_BLE);	//因为会动态修改该串口参数，所以假定它处于使能状态，需先禁止。
	
	/*配置串口：中断接收，查询发送。
	帧格式：
	0：无校验：2位停止位
	1：奇校验，1位停止位；
	2：偶校验，1位停止位；
	3：无校验，1位停止位；
	波特率：
	0  9600");
	1  19200");
	2  38400");
	3  57600");
	4  115200");
	*/
//	if(0 == mode)
//		uart_to_ble_cfg.fmt= MODE_8_n_2;
//	else if(1 == mode)
//		uart_to_ble_cfg.fmt= MODE_8_O_1;
//	else if(2 == mode)
//		uart_to_ble_cfg.fmt= MODE_8_E_1;
//	else if(3 == mode)
//		uart_to_ble_cfg.fmt= MODE_8_n_1;
//	else
//		uart_to_ble_cfg.fmt= MODE_8_E_1;
//	
//	if( (0 != baud)  &&
//		(1 != baud) &&
//		(2 != baud) &&
//		(3 != baud) &&
//		(4 != baud) )		
//		uart_to_ble_cfg.baud= 0;	
//	else
//		uart_to_ble_cfg.baud= baud;
	
	uart_to_ble_cfg.baud= baud;
	strcpy(uart_to_ble_cfg.fmt, fmt);
	uart_to_ble_cfg.sta= 0;
	
	//C OVER8@CR1=0, 16 samples.
	/* baudrate= fck/(8*(2-OVER8)*UARTDIV). UARTDIV= man.fra.
	例fpclk=84MHz，16samples，115200时，man.fra=45.5625，即0x2D9。
	具体参考RM0090's P978。
	*/
	bsp_uart_ble_config(uart_to_ble_cfg.fmt, uart_to_ble_cfg.baud, 0);	//9600/19200/38400/57600

	
	LL_USART_EnableDirectionTx(UART_BLE);
	LL_USART_EnableDirectionRx(UART_BLE);
	LL_USART_Enable(UART_BLE);
	
	LL_USART_EnableIT_RXNE(UART_BLE);
	
	
	/* preemption = 1, sub-priority = 1 */
	NVIC_SetPriority(UART_BLE_IRQn, 1);
	/* Enable Interrupt for UART0 channel */
	NVIC_EnableIRQ(UART_BLE_IRQn);
}

/************************ END OF FILE ************************/






